#include "viml/debug_info.h"
#include "viml/value.h"
#include <fstream>
#include <sstream>
#include <algorithm>
#include <iostream>

namespace viml {

// SourceLocation 实现
std::string SourceLocation::to_string() const {
    std::ostringstream oss;
    oss << file;
    if (line > 0) {
        oss << ":" << line;
        if (column > 0) {
            oss << ":" << column;
        }
    }
    return oss.str();
}

// DebugInfo 实现
DebugInfo::DebugInfo(const std::string& filename)
    : source_file(filename), next_breakpoint_id(1) {
    if (!source_file.empty()) {
        load_source_file();
    }
}

void DebugInfo::set_source_file(const std::string& filename) {
    source_file = filename;
    source_lines.clear();
    line_to_pc.clear();
    pc_to_line.clear();

    if (!source_file.empty()) {
        load_source_file();
    }
}

bool DebugInfo::load_source_file() {
    if (source_file.empty()) {
        return false;
    }

    std::ifstream file(source_file);
    if (!file.is_open()) {
        return false;
    }

    source_lines.clear();
    std::string line;
    while (std::getline(file, line)) {
        source_lines.push_back(line);
    }

    return true;
}

std::string DebugInfo::get_source_line(int line) const {
    if (line < 1 || line > static_cast<int>(source_lines.size())) {
        return "";
    }
    return source_lines[line - 1];
}

// 行号映射实现
void DebugInfo::add_line_mapping(int line, size_t pc) {
    line_to_pc[line] = pc;
    pc_to_line[pc] = line;
}

size_t DebugInfo::pc_for_line(int line) const {
    auto it = line_to_pc.find(line);
    return (it != line_to_pc.end()) ? it->second : static_cast<size_t>(-1);
}

int DebugInfo::line_for_pc(size_t pc) const {
    auto it = pc_to_line.find(pc);
    return (it != pc_to_line.end()) ? it->second : -1;
}

SourceLocation DebugInfo::get_location(size_t pc) const {
    int line = line_for_pc(pc);
    if (line > 0) {
        return SourceLocation(source_file, line);
    }
    return SourceLocation(source_file);
}

bool DebugInfo::has_line_mapping(int line) const {
    return line_to_pc.find(line) != line_to_pc.end();
}

bool DebugInfo::has_pc_mapping(size_t pc) const {
    return pc_to_line.find(pc) != pc_to_line.end();
}

// 函数信息管理
void DebugInfo::add_function(const FunctionInfo& func) {
    functions[func.name] = func;

    // 维护函数定义顺序
    if (std::find(function_order.begin(), function_order.end(), func.name) == function_order.end()) {
        function_order.push_back(func.name);
    }
}

void DebugInfo::add_function(const std::string& name, const SourceLocation& location,
                            size_t start_pc, size_t end_pc,
                            const std::vector<std::string>& params) {
    FunctionInfo func(name, location, start_pc, end_pc);
    func.params = params;
    add_function(func);
}

const FunctionInfo* DebugInfo::get_function(const std::string& name) const {
    auto it = functions.find(name);
    return (it != functions.end()) ? &it->second : nullptr;
}

const FunctionInfo* DebugInfo::get_function_at_pc(size_t pc) const {
    for (const auto& pair : functions) {
        const FunctionInfo& func = pair.second;
        if (pc >= func.start_pc && pc <= func.end_pc) {
            return &func;
        }
    }
    return nullptr;
}

std::vector<std::string> DebugInfo::get_function_names() const {
    return function_order;
}

std::vector<const FunctionInfo*> DebugInfo::get_functions_in_range(size_t start_pc, size_t end_pc) const {
    std::vector<const FunctionInfo*> result;
    for (const auto& pair : functions) {
        const FunctionInfo& func = pair.second;
        if (func.start_pc <= end_pc && func.end_pc >= start_pc) {
            result.push_back(&func);
        }
    }
    return result;
}

// 变量信息管理
void DebugInfo::add_variable(const VariableInfo& var) {
    variables.push_back(var);
}

void DebugInfo::add_variable(const std::string& name, const SourceLocation& location,
                            const std::string& scope, size_t register_index,
                            size_t start_pc, size_t end_pc) {
    VariableInfo var(name, location, scope, register_index, start_pc, end_pc);
    variables.push_back(var);
}

const VariableInfo* DebugInfo::get_variable(const std::string& name) const {
    for (const auto& var : variables) {
        if (var.name == name) {
            return &var;
        }
    }
    return nullptr;
}

std::vector<const VariableInfo*> DebugInfo::get_variables_at_pc(size_t pc) const {
    std::vector<const VariableInfo*> result;
    for (const auto& var : variables) {
        if (pc >= var.start_pc && pc <= var.end_pc) {
            result.push_back(&var);
        }
    }
    return result;
}

std::vector<const VariableInfo*> DebugInfo::get_variables_in_scope(size_t pc, const std::string& function_name) const {
    std::vector<const VariableInfo*> result;

    for (const auto& var : variables) {
        // 如果指定了函数名，优先匹配该函数内的变量
        if (!function_name.empty()) {
            const FunctionInfo* func = get_function(function_name);
            if (func && pc >= func->start_pc && pc <= func->end_pc) {
                if (pc >= var.start_pc && pc <= var.end_pc && var.scope == "local") {
                    // 检查变量是否在函数内部定义
                    if (var.location.line >= func->location.line &&
                        var.location.line <= func->location.line + 100) { // 简化的范围检查
                        result.push_back(&var);
                    }
                }
            }
        } else {
            // 如果没有指定函数，返回所有在PC位置的变量
            if (pc >= var.start_pc && pc <= var.end_pc) {
                result.push_back(&var);
            }
        }
    }

    return result;
}

std::vector<const VariableInfo*> DebugInfo::get_local_variables(const std::string& function_name) const {
    std::vector<const VariableInfo*> result;
    const FunctionInfo* func = get_function(function_name);

    if (!func) {
        return result;
    }

    for (const auto& var : variables) {
        if (var.scope == "local" && var.location.line >= func->location.line) {
            // 简化检查：函数名之后定义的局部变量
            result.push_back(&var);
        }
    }

    return result;
}

// 断点管理
size_t DebugInfo::add_breakpoint(int line, const std::string& condition) {
    SourceLocation location(source_file, line);
    return add_breakpoint(location, condition);
}

size_t DebugInfo::add_breakpoint(const SourceLocation& location, const std::string& condition) {
    size_t pc = pc_for_line(location.line);

    BreakpointInfo bp(next_breakpoint_id++, location, pc, true);
    bp.condition = condition;

    breakpoints[bp.id] = bp;
    update_line_breakpoint_map();

    return bp.id;
}

size_t DebugInfo::add_breakpoint(size_t pc, const std::string& condition) {
    int line = line_for_pc(pc);
    SourceLocation location(source_file, line);

    BreakpointInfo bp(next_breakpoint_id++, location, pc, true);
    bp.condition = condition;

    breakpoints[bp.id] = bp;
    update_line_breakpoint_map();

    return bp.id;
}

bool DebugInfo::remove_breakpoint(size_t breakpoint_id) {
    auto it = breakpoints.find(breakpoint_id);
    if (it != breakpoints.end()) {
        breakpoints.erase(it);
        update_line_breakpoint_map();
        return true;
    }
    return false;
}

bool DebugInfo::remove_breakpoint(int line) {
    const BreakpointInfo* bp = get_breakpoint_at_line(line);
    if (bp) {
        return remove_breakpoint(bp->id);
    }
    return false;
}

bool DebugInfo::enable_breakpoint(size_t breakpoint_id, bool enabled) {
    auto it = breakpoints.find(breakpoint_id);
    if (it != breakpoints.end()) {
        it->second.enabled = enabled;
        update_line_breakpoint_map();
        return true;
    }
    return false;
}

bool DebugInfo::disable_breakpoint(size_t breakpoint_id) {
    return enable_breakpoint(breakpoint_id, false);
}

const BreakpointInfo* DebugInfo::get_breakpoint(size_t breakpoint_id) const {
    auto it = breakpoints.find(breakpoint_id);
    return (it != breakpoints.end()) ? &it->second : nullptr;
}

const BreakpointInfo* DebugInfo::get_breakpoint_at_line(int line) const {
    auto it = line_breakpoints.find(line);
    if (it != line_breakpoints.end()) {
        return get_breakpoint(it->second);
    }
    return nullptr;
}

const BreakpointInfo* DebugInfo::get_breakpoint_at_pc(size_t pc) const {
    for (const auto& pair : breakpoints) {
        if (pair.second.pc == pc && pair.second.enabled) {
            return &pair.second;
        }
    }
    return nullptr;
}

std::vector<const BreakpointInfo*> DebugInfo::get_all_breakpoints() const {
    std::vector<const BreakpointInfo*> result;
    for (const auto& pair : breakpoints) {
        result.push_back(&pair.second);
    }
    return result;
}

std::vector<const BreakpointInfo*> DebugInfo::get_enabled_breakpoints() const {
    std::vector<const BreakpointInfo*> result;
    for (const auto& pair : breakpoints) {
        if (pair.second.enabled) {
            result.push_back(&pair.second);
        }
    }
    return result;
}

bool DebugInfo::has_breakpoint_at_line(int line) const {
    return line_breakpoints.find(line) != line_breakpoints.end();
}

bool DebugInfo::has_breakpoint_at_pc(size_t pc) const {
    return get_breakpoint_at_pc(pc) != nullptr;
}

void DebugInfo::clear_all_breakpoints() {
    breakpoints.clear();
    line_breakpoints.clear();
    next_breakpoint_id = 1;
}

// 断点命中处理
bool DebugInfo::should_break(size_t pc, const std::unordered_map<std::string, Value>& variables) {
    const BreakpointInfo* bp = get_breakpoint_at_pc(pc);
    if (!bp || !bp->enabled) {
        return false;
    }

    // 检查忽略次数
    if (bp->ignore_count > 0) {
        // 这是一个简化的处理，实际实现可能需要修改断点对象
        return false;
    }

    // 检查条件
    if (!bp->condition.empty()) {
        return evaluate_breakpoint_condition(bp->condition, variables);
    }

    return true;
}

void DebugInfo::hit_breakpoint(size_t breakpoint_id) {
    auto it = breakpoints.find(breakpoint_id);
    if (it != breakpoints.end()) {
        it->second.hit_count++;
    }
}

void DebugInfo::set_breakpoint_condition(size_t breakpoint_id, const std::string& condition) {
    auto it = breakpoints.find(breakpoint_id);
    if (it != breakpoints.end()) {
        it->second.condition = condition;
    }
}

void DebugInfo::set_breakpoint_ignore_count(size_t breakpoint_id, int ignore_count) {
    auto it = breakpoints.find(breakpoint_id);
    if (it != breakpoints.end()) {
        it->second.ignore_count = ignore_count;
    }
}

// 执行上下文管理
void DebugInfo::set_call_stack(const std::vector<std::string>& stack) {
    call_stack = stack;
}

void DebugInfo::update_variable_value(const std::string& name, const Value& value) {
    variable_values[name] = value;
}

Value DebugInfo::get_variable_value(const std::string& name) const {
    auto it = variable_values.find(name);
    return (it != variable_values.end()) ? it->second : Value();
}

void DebugInfo::clear_variable_values() {
    variable_values.clear();
}

// 调试信息查询
std::vector<SourceLocation> DebugInfo::get_executable_locations() const {
    std::vector<SourceLocation> result;
    for (const auto& pair : pc_to_line) {
        result.push_back(SourceLocation(source_file, pair.second));
    }
    return result;
}

std::vector<int> DebugInfo::get_executable_lines() const {
    std::vector<int> result;
    for (const auto& pair : line_to_pc) {
        result.push_back(pair.first);
    }
    std::sort(result.begin(), result.end());
    return result;
}

bool DebugInfo::is_executable_line(int line) const {
    return line_to_pc.find(line) != line_to_pc.end();
}

bool DebugInfo::is_valid_pc(size_t pc) const {
    return pc_to_line.find(pc) != pc_to_line.end();
}

// 格式化和输出
std::string DebugInfo::format_location(const SourceLocation& location) const {
    std::ostringstream oss;
    oss << location.to_string();

    if (location.line > 0 && location.line <= static_cast<int>(source_lines.size())) {
        oss << " -> \"" << source_lines[location.line - 1] << "\"";
    }

    return oss.str();
}

std::string DebugInfo::format_breakpoint(const BreakpointInfo& bp) const {
    std::ostringstream oss;
    oss << "断点 " << bp.id << " at " << format_location(bp.location);

    if (!bp.enabled) {
        oss << " (disabled)";
    }

    if (bp.hit_count > 0) {
        oss << " (hit " << bp.hit_count << " times)";
    }

    if (!bp.condition.empty()) {
        oss << " (condition: " << bp.condition << ")";
    }

    return oss.str();
}

std::string DebugInfo::format_function(const FunctionInfo& func) const {
    std::ostringstream oss;
    oss << "函数 " << func.name << " at " << format_location(func.location);
    oss << " [PC: " << func.start_pc << "-" << func.end_pc << "]";

    if (!func.params.empty()) {
        oss << " params: (";
        for (size_t i = 0; i < func.params.size(); ++i) {
            if (i > 0) oss << ", ";
            oss << func.params[i];
        }
        oss << ")";
    }

    return oss.str();
}

std::string DebugInfo::format_variable(const VariableInfo& var) const {
    std::ostringstream oss;
    oss << var.scope << " var " << var.name;
    oss << " at " << format_location(var.location);
    oss << " [PC: " << var.start_pc << "-" << var.end_pc << "]";

    if (var.register_index != 0) {
        oss << " [R" << var.register_index << "]";
    }

    return oss.str();
}

// 统计信息
DebugInfo::DebugStatistics DebugInfo::get_statistics() const {
    DebugStatistics stats;
    stats.total_functions = functions.size();
    stats.total_variables = variables.size();
    stats.total_breakpoints = breakpoints.size();
    stats.total_line_mappings = line_to_pc.size();

    for (const auto& pair : breakpoints) {
        if (pair.second.enabled) {
            stats.enabled_breakpoints++;
        }
    }

    return stats;
}

// 清理和重置
void DebugInfo::clear() {
    source_lines.clear();
    line_to_pc.clear();
    pc_to_line.clear();
    functions.clear();
    function_order.clear();
    variables.clear();
    breakpoints.clear();
    line_breakpoints.clear();
    call_stack.clear();
    variable_values.clear();
    next_breakpoint_id = 1;
}

void DebugInfo::reset() {
    clear();
    if (!source_file.empty()) {
        load_source_file();
    }
}

// 私有辅助方法
bool DebugInfo::evaluate_breakpoint_condition(const std::string& condition,
                                             const std::unordered_map<std::string, Value>& variables) const {
    // 简化的条件评估实现
    // 在实际实现中，这里应该集成一个表达式解析器

    // 简单的变量存在性检查
    if (condition.find("==") == std::string::npos &&
        condition.find("!=") == std::string::npos &&
        condition.find(">") == std::string::npos &&
        condition.find("<") == std::string::npos) {
        // 如果只是变量名，检查变量是否存在且非空
        auto it = variables.find(condition);
        if (it != variables.end()) {
            return !it->second.is_nil();
        }
        return false;
    }

    // 对于复杂表达式，暂时返回true（简化处理）
    // 在完整实现中应该添加表达式解析和求值逻辑
    return true;
}

void DebugInfo::update_line_breakpoint_map() {
    line_breakpoints.clear();
    for (const auto& pair : breakpoints) {
        const BreakpointInfo& bp = pair.second;
        if (bp.enabled && bp.location.line > 0) {
            line_breakpoints[bp.location.line] = bp.id;
        }
    }
}

std::string DebugInfo::extract_function_context(size_t pc) const {
    const FunctionInfo* func = get_function_at_pc(pc);
    if (func) {
        return func->name;
    }
    return "";
}

} // namespace viml